package com.example.aidocengine.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.aidocengine.common.constant.BusinessConstant;
import com.example.aidocengine.common.exception.BusinessException;
import com.example.aidocengine.common.result.ResultCode;
import com.example.aidocengine.common.utils.FileUtils;
import com.example.aidocengine.mapper.CommandingUnitMapper;
import com.example.aidocengine.mapper.DeviceInfoMapper;
import com.example.aidocengine.mapper.DeviceTemplateImportMapper;
import com.example.aidocengine.pojo.dto.response.DeviceImportResponse;
import com.example.aidocengine.pojo.entity.CommandingUnit;
import com.example.aidocengine.pojo.entity.DeviceInfo;
import com.example.aidocengine.pojo.entity.DeviceTemplateImport;
import com.example.aidocengine.processor.ExcelProcessor;
import com.example.aidocengine.service.DeviceImportService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
public class DeviceImportServiceImpl implements DeviceImportService {

    @Autowired
    private ExcelProcessor excelProcessor;

    @Autowired
    private DeviceTemplateImportMapper deviceTemplateImportMapper;

    @Autowired
    private CommandingUnitMapper commandingUnitMapper;

    @Autowired
    private DeviceInfoMapper deviceInfoMapper;

    @Value("${file.upload.device-template}")
    private String deviceTemplateDir;

    /**
     * 导入设备模板数据，支持解析Excel文件并批量插入或更新设备信息和受令单位。
     * <p>
     * 验证上传的文件是否合法，然后创建一条导入记录，并解析Excel中的内容。
     * 解析完成后，分别处理受令单位和设备信息数据，进行去重、过滤、批量插入或更新操作。
     * 最后更新导入记录的状态，并返回导入结果。
     *
     * @param file        上传的Excel文件，包含设备模板数据
     * @param doClear     导入前，是否清空数据库中的数据，true表示清空，false表示新增
     * @param description 导入描述信息（当前未使用）
     * @return DeviceImportResponse 导入结果响应对象，包含导入统计信息
     * @throws BusinessException 当文件无效或导入过程中发生错误时抛出业务异常
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public DeviceImportResponse importDeviceTemplate(MultipartFile file,Boolean doClear, String description) {
        log.info("开始导入设备模板，文件名：{}", file.getOriginalFilename());

        // 验证文件
        if (!FileUtils.isValidFile(file)) {
            throw new BusinessException(ResultCode.FILE_UPLOAD_ERROR.getCode(), "无效的文件格式或文件为空");
        }

        // 创建导入记录
        DeviceTemplateImport importRecord = new DeviceTemplateImport();
        importRecord.setImportFileName(file.getOriginalFilename());
        importRecord.setImportTime(LocalDateTime.now());
        importRecord.setImportStatus(0); // 0:导入中
        importRecord.setOperator("system");

        deviceTemplateImportMapper.insert(importRecord);

        try {
            // 先解析Excel文件
            Map<String, Object> parseResult = excelProcessor.parseDeviceTemplateExcel(file);
            
            // 解析成功后再保存文件（可选，如果不需要保存文件则去掉）
            // String filePath = FileUtils.saveFile(file, deviceTemplateDir);
            
            @SuppressWarnings("unchecked")
            List<CommandingUnit> commandingUnits = (List<CommandingUnit>) parseResult.get("commandingUnits");
            
            @SuppressWarnings("unchecked")
            List<DeviceInfo> deviceInfos = (List<DeviceInfo>) parseResult.get("deviceInfos");
            
            int totalRecords = (Integer) parseResult.get("totalRecords");
            int successRecords = 0;
            int failedRecords = 0;

            //处理受令单位数据
            if (doClear){
                //删除数据库的旧受令单位。其中oldCommandingUnits存储删除的数据
                List<CommandingUnit> oldCommandingUnits = commandingUnitMapper.selectList(null);
                commandingUnitMapper.deleteAll();
                log.info("删除数据库的旧受令单位，共{}条记录，再导入新的受令单位", oldCommandingUnits.size());
            }else {
                log.info("新增导入受令单位记录");
            }

            // 对新读取的数据（受令单位）进行过滤和去重
            if (commandingUnits != null && !commandingUnits.isEmpty()) {
                for (CommandingUnit unit : commandingUnits) {
                    try {
                        // 检查是否已存在
                        QueryWrapper<CommandingUnit> wrapper = new QueryWrapper<>();
                        wrapper.eq("unit_name", unit.getUnitName());
                        CommandingUnit existing = commandingUnitMapper.selectOne(wrapper);

                        if (existing == null) {
                            commandingUnitMapper.insert(unit);successRecords++;
                        } else {
                            log.info("受令单位已存在，无需导入{}", existing.toString());
                            failedRecords++;
                        }

                    } catch (Exception e) {
                        log.warn("导入受令单位失败：{}, 错误：{}", unit.getUnitName(), e.getMessage());
                        failedRecords++;
                    }
                }
            }

            // 处理设备信息数据
            if (doClear){
                log.info("删除数据库的旧设备信息");
                deviceInfoMapper.deleteAll();
            }else {
                log.info("新增导入设备记录");
            }
            if (deviceInfos != null && !deviceInfos.isEmpty()) {
                log.info("开始处理设备信息数据，共{}条记录", deviceInfos.size());
                // 对数据进行过滤和去重，使用复合键确保合并单元格中的每行数据都被保留
                Map<String, DeviceInfo> deviceMap = new LinkedHashMap<>();
                int processedCount = 0;
                int validCount = 0;
                int invalidCount = 0;
                
                for (DeviceInfo device : deviceInfos) {
                    processedCount++;
                    String deviceDoubleCode = device.getDeviceDoubleCode();
                    String stationName = device.getStationName();
                    String deviceName = device.getDeviceName();
                    String deviceCode = device.getDeviceCode();
                    
                    log.debug("处理第{}条设备记录：厂站='{}', 设备双编='{}', 设备名称='{}', 设备编号='{}'", 
                             processedCount, stationName, deviceDoubleCode, deviceName, deviceCode);
                    
                    // 只要有厂站名称和设备双编就认为是有效数据
                    if (deviceDoubleCode != null && !deviceDoubleCode.trim().isEmpty() &&
                        !"null".equals(deviceDoubleCode.trim()) &&
                        stationName != null && !stationName.trim().isEmpty() && 
                        !"null".equals(stationName.trim()) &&
                        // 排除明显的模板头部信息和说明文字
                        !deviceDoubleCode.contains("设备双编") && 
                        !deviceDoubleCode.contains("填写说明") &&
                        !stationName.equals("厂站") && 
                        !stationName.equals("厂站名称") &&
                        !stationName.contains("填写说明") &&
                        // 允许示例数据通过，移除严格的长度限制
                        deviceDoubleCode.length() < 500) { // 放宽长度限制以允许示例数据
                        
                        log.info("✓ 有效设备数据：厂站='{}', 设备双编='{}', 设备名称='{}', 设备编号='{}'", 
                                stationName, deviceDoubleCode, deviceName, deviceCode);
                        
                        // 使用复合键确保每条记录的唯一性，包含多个字段以避免合并单元格导致的数据丢失
                        // 组合键：厂站名称 + 设备双编 + 设备名称 + 设备编号
                        String compositeKey = String.format("%s|%s|%s|%s", 
                                stationName != null ? stationName : "",
                                deviceDoubleCode != null ? deviceDoubleCode : "",
                                deviceName != null ? deviceName : "",
                                deviceCode != null ? deviceCode : "");
                        
                        // 只有在复合键完全相同时才认为是重复记录
                        deviceMap.put(compositeKey, device);
                        validCount++;
                    } else {
                        log.info("✗ 跳过无效设备：厂站='{}', 设备双编='{}', 设备名称='{}', 设备编号='{}'", 
                                stationName, deviceDoubleCode, deviceName, deviceCode);
                        invalidCount++;
                    }
                }
                List<DeviceInfo> uniqueDeviceInfos = new ArrayList<>(deviceMap.values());
                log.info("设备数据处理统计：总处理={}，有效={}，无效={}，去重后={}", 
                         processedCount, validCount, invalidCount, uniqueDeviceInfos.size());
                
                // 按批次处理，避免一次性插入过多数据
                int batchSize = 100;
                List<DeviceInfo> updateList = new ArrayList<>();
                List<DeviceInfo> insertList = new ArrayList<>();
                
                for (DeviceInfo device : uniqueDeviceInfos) {
                    try {
                        // 检查是否已存在
                        DeviceInfo existing = deviceInfoMapper.selectByDeviceDoubleCode(device.getDeviceDoubleCode());

                        /*
                        //bug处原代码，以设备双编作为唯一判定将导致同一种设备无法在多个厂站同时使用，更新逻辑导致莫名消失
                        if (existing == null) {
                            log.info("✓ 准备插入新设备：{}", device.getDeviceDoubleCode());
                            insertList.add(device);
                        } else {
                            log.info("⚠ 设备已存在，准备更新：{}", device.getDeviceDoubleCode());
                            // 更新现有记录
                            existing.setStationName(device.getStationName());
                            existing.setVoltageLevel(device.getVoltageLevel());
                            existing.setDeviceName(device.getDeviceName());
                            existing.setDeviceCode(device.getDeviceCode());
                            existing.setDeviceType(device.getDeviceType());
                            existing.setDeviceCategory(device.getDeviceCategory());
                            existing.setUpdatedTime(LocalDateTime.now());
                            updateList.add(existing);
                        }
                         */
                        if (existing == null){
                            log.info("✓ 准备插入新设备：{}", device.getDeviceDoubleCode());
                            insertList.add(device);
                        }else if (existing.getDeviceDoubleCode().equals(device.getDeviceDoubleCode())
                                && existing.getStationName().equals(device.getStationName())
                                && existing.getDeviceName().equals(device.getDeviceName())
                                && existing.getDeviceCode().equals(device.getDeviceCode())
                                && existing.getDeviceType().equals(device.getDeviceType())
                                && existing.getDeviceCategory().equals(device.getDeviceCategory())
                                && existing.getVoltageLevel().equals(device.getVoltageLevel()))
                        {
                            log.info("⚠ 设备已存在，跳过处理：{}", device.getDeviceDoubleCode());
                            failedRecords++;
                        }else {
                            //存在同双编但有不同属性
                            log.info("✓ 准备插入设备（有同双编存在）谨慎检查导入文档：{}", device.getDeviceDoubleCode());
                            insertList.add(device);
                        }

                        // 批量处理
                        if (insertList.size() >= batchSize) {
                            log.info("🔄 执行批量插入，数量：{}", insertList.size());
                            try {
                                deviceInfoMapper.insertBatch(insertList);
                                successRecords += insertList.size();
                                log.info("✅ 批量插入成功：{} 条记录", insertList.size());
                            } catch (Exception e) {
                                log.error("❌ 批量插入失败：{}", e.getMessage());
                                // 逐条插入，跳过重复的
                                for (DeviceInfo failedDevice : insertList) {
                                    try {
                                        deviceInfoMapper.insert(failedDevice);
                                        successRecords++;
                                    } catch (Exception singleError) {
                                        log.warn("⚠ 跳过重复设备：{} - {}", failedDevice.getDeviceDoubleCode(), singleError.getMessage());
                                        failedRecords++;
                                    }
                                }
                            }
                            insertList.clear();
                        }
                        
                        if (updateList.size() >= batchSize) {
                            for (DeviceInfo updateDevice : updateList) {
                                deviceInfoMapper.updateById(updateDevice);
                            }
                            successRecords += updateList.size();
                            updateList.clear();
                        }
                        
                    } catch (Exception e) {
                        log.warn("导入设备信息失败：{}, 错误：{}", device.getDeviceDoubleCode(), e.getMessage());
                        failedRecords++;
                    }
                }
                
                // 处理剩余数据
                if (!insertList.isEmpty()) {
                    log.info("🔄 执行剩余批量插入，数量：{}", insertList.size());
                    try {
                        deviceInfoMapper.insertBatch(insertList);
                        successRecords += insertList.size();
                        log.info("✅ 剩余批量插入成功：{} 条记录", insertList.size());
                    } catch (Exception e) {
                        log.error("❌ 剩余批量插入失败：{}", e.getMessage());
                        // 逐条插入，跳过重复的
                        for (DeviceInfo failedDevice : insertList) {
                            try {
                                deviceInfoMapper.insert(failedDevice);
                                successRecords++;
                            } catch (Exception singleError) {
                                log.warn("⚠ 跳过重复设备：{} - {}", failedDevice.getDeviceDoubleCode(), singleError.getMessage());
                                failedRecords++;
                            }
                        }
                    }
                }
                
                if (!updateList.isEmpty()) {
                    for (DeviceInfo updateDevice : updateList) {
                        deviceInfoMapper.updateById(updateDevice);
                    }
                    successRecords += updateList.size();
                }
            }

            // 更新导入记录
            importRecord.setSuccessCount(successRecords);
            importRecord.setFailCount(failedRecords);
            importRecord.setImportStatus(1); // 1:成功
            deviceTemplateImportMapper.updateById(importRecord);

            log.info("设备模板导入完成，总记录数：{}, 成功：{}, 失败：{}", totalRecords, successRecords, failedRecords);

            // 构造返回结果
            DeviceImportResponse response = new DeviceImportResponse();
            response.setImportId(importRecord.getId());
            response.setTotalRecords(totalRecords);
            response.setSuccessRecords(successRecords);
            response.setFailedRecords(failedRecords);
            response.setStatus("COMPLETED");
            response.setMessage("导入完成");

            return response;

        } catch (Exception e) {
            log.error("设备模板导入失败：", e);
            
            // 更新导入记录为失败状态
            importRecord.setImportStatus(2); // 2:失败
            importRecord.setErrorMessage(e.getMessage());
            deviceTemplateImportMapper.updateById(importRecord);

            throw new BusinessException(ResultCode.DEVICE_IMPORT_ERROR.getCode(), "设备模板导入失败：" + e.getMessage());
        }
    }

    @Override
    public DeviceImportResponse getImportRecord(Long importId) {
        DeviceTemplateImport record = deviceTemplateImportMapper.selectById(importId);
        if (record == null) {
            throw new BusinessException(ResultCode.NOT_FOUND.getCode(), "导入记录不存在");
        }

        DeviceImportResponse response = new DeviceImportResponse();
        response.setImportId(record.getId());
        response.setTotalRecords(record.getSuccessCount() + record.getFailCount()); // 计算总记录数
        response.setSuccessRecords(record.getSuccessCount());
        response.setFailedRecords(record.getFailCount());
        response.setStatus(record.getImportStatus().toString());
        response.setMessage(record.getErrorMessage());

        return response;
    }

    @Override
    public List<DeviceInfo> getDeviceList() {
        log.info("查询设备列表");
        return deviceInfoMapper.selectList(null);
    }
    
    @Override
    public List<CommandingUnit> getCommandingUnitList() {
        log.info("查询受令单位列表");
        return commandingUnitMapper.selectList(null);
    }
}